package org.example.hashAndSet;

import org.example.pojo.Student;

import java.util.HashMap;
import java.util.HashSet;
import java.util.TreeSet;

/**
 * 哈希表
 * 哈希表是一种数据结构，它通过把键映射到索引位置来快速访问数据。
 * 哈希表的实现有两种：
 * 1. 直接寻址法：通过直接计算索引位置来访问数据。
 * 2. 开放寻址法：当发生哈希冲突时，通过重新探测空闲位置来解决冲突。
 * 哈希表的优点：
 * 1. 快速访问：通过哈希函数，可以快速找到数据的索引位置，从而快速访问数据。
 * 2. 节省空间：哈希表的空间利用率高，可以节省空间。
 * 3. 无序性：哈希表无序性，可以快速访问数据，但是不能通过索引位置直接访问数据。
 * 4. 唯一性：哈希表的键值唯一，不能重复。
 * 5. 线程安全：哈希表是线程安全的，可以在多线程环境下使用。
 * 6. 灵活性：哈希表的大小可以动态调整，可以根据需要增加或减少。
 * 7. 负载因子：哈希表的负载因子表示哈希表的填充率，当负载因子大于某个阈值时，需要重新哈希。
 * 8. 哈希冲突：哈希冲突是指不同的键值映射到相同的索引位置。解决哈希冲突的方法有：
 * 1. 开放寻址法：当发生哈希冲突时，通过重新探测空闲位置来解决冲突。
 * 2. 链地址法：当发生哈希冲突时，将冲突的键值存储在链表中。
 * 9. 性能：哈希表的性能优于顺序表，在查找、插入、删除操作时，平均时间复杂度为O(1)。
 * 10. 适用场景：哈希表适用于需要快速访问的数据，如字典、数据库索引等。
 * 11. 哈希表的实现：
 * 1. 数组：通过数组实现哈希表，数组的索引位置即为哈希值。
 * 2. 链表：当发生哈希冲突时，将冲突的键值存储在链表中。
 * 3. 二叉树：当哈希表的大小超过一定阈值时，可以采用二叉树来实现哈希表。
 * 4. 平衡树：当哈希表的大小超过一定阈值时，可以采用平衡树来实现哈希表。
 * 5. 哈希函数：哈希函数是一种从键到索引位置的映射函数，它通过计算键的哈希值来计算索引位置。
 * 6. 冲突解决方法：当发生哈希冲突时，需要解决冲突的方法有开放寻址法和链地址法。
 * set 和 map 的区别：
 * 1. 存储方式：set 存储的是元素，map 存储的是键值对。
 * 2. 存储顺序：set 无序，map 有序。
 * 3. 键值唯一：set 元素唯一，map 键值唯一。
 * 4. 访问速度：set 访问速度快，map 访问速度慢。
 * 5. 线程安全：set 线程不安全，map 线程安全。
 */
public class HashAndSet {
    public static void main(String[] args) {
        HashSet<Integer> set = new HashSet<>();

        set.add(1);
        set.add(2);
        set.add(3);
        System.out.println(set);

        HashMap<Integer, String> map = new HashMap<>();
        map.put(1,"zhangsan");

        System.out.println(map.get(1));

        System.out.println("------------------------");
        HashSet<Student> studentSet = new HashSet<>();
        Student  st1 = new Student("zhangsan",18);
        Student st2 = new Student("lisi", 19);
        studentSet.add(st1);
        studentSet.add(st2);
        System.out.println(st1.hashCode());
        System.out.println(st2.hashCode());


        System.out.println(studentSet);
        System.out.println(studentSet.stream().findFirst());
        System.out.println("---------------------有序表--------------------");

        /**
         * TreeSet 实现有序集合，底层使用红黑树实现，具有排序、查找、删除操作的能力。
         * 红黑树是一种自平衡的二叉查找树，它保证了插入、删除、查找操作的平均时间复杂度为O(logN)。
         * 红黑树的插入、删除操作的时间复杂度为O(logN)，查找操作的时间复杂度为O(logN)。
         * 因此，TreeSet 具有快速的查找、删除操作的能力，但插入操作的平均时间复杂度为O(logN)。
         * 另外，TreeSet 还可以按照排序顺序遍历集合中的元素。
         * 因此，TreeSet 适合于需要排序、查找、删除操作的场景。
         */
        TreeSet<Integer> treeSet = new TreeSet<>(); // 红黑树
        treeSet.add(5);
        treeSet.add(2);
        treeSet.add(3);
        System.out.println(treeSet);

    }
}
